﻿#region Header
// Copyright (c) 2015 OPEN TONE, Inc.
// Released under the MIT license
// http://opensource.org/licenses/mit-license.php
#endregion
using System.Runtime.CompilerServices;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using System;

namespace OpenXmlLib.Excel.Impl
{
	public class CellImpl : ICell
	{
		// Cellオブジェクト
		private readonly Cell cell;

		/// <summary>
		/// このCellを持つIWorksheetオブジェクト
		/// </summary>
		public IWorksheet Worksheet { get; private set; }

		/// <summary>
		/// privateコンストラクタ
		/// </summary>
		private CellImpl() { }

		/// <summary>
		/// コンストラクタ
		/// </summary>
		/// <param name="worksheet">IWorksheetオブジェクト</param>
		internal CellImpl(IWorksheet worksheet) : this(worksheet, null)
		{
		}

		/// <summary>
		/// コンストラクタ
		/// </summary>
		/// <param name="worksheet">IWorksheetオブジェクト</param>
		/// <param name="cell">Cellオブジェクト</param>
		internal CellImpl(IWorksheet worksheet, Cell cell)
		{
			this.Worksheet = worksheet;
			this.cell = cell;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		/// <see cref="ICell.IsEmpty"/>
		public bool IsEmpty()
		{
			return (null == this.cell) ? true : false;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		/// <see cref="ICell.IsFormula"/>
		public bool IsFormula()
		{
			bool result = !IsEmpty() && (null != this.cell.CellFormula);
			return result;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		/// <see cref="ICell.GetStringValue"/>
		public String GetStringValue()
		{
			String value = "";
			if (!IsEmpty())
			{
				value = this.cell.CellValue.InnerText;
				// 文字列またはbool値、数式を含む場合の処理
				if (IsSharedStringTable())
				{
					value = GetValueFromSharedString(value);
				}
				else if (IsBoolean())
				{
					value = ConvertToBoolean(value);
				}
			}
			return value;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		/// <see cref="ICell.GetBooleanValue"/>
		public bool? GetBooleanValue()
		{
			bool? result = null;
			if (IsBoolean())
			{
				result = !("0".Equals(this.cell.CellValue.InnerText));
			}
			return result;
		}

		/// <summary>
		/// SharedStringTableからセル値を取得します。
		/// </summary>
		/// <param name="index">SharedStringTable内のインデックス値</param>
		/// <returns>セル値</returns>
		private String GetValueFromSharedString(String index)
		{
			ISharedStringTable sst = Worksheet.Workbook.SharedStringTable;
			String value = sst.ElementAt(Convert.ToInt32(index));
			return value;
		}

		/// <summary>
		/// 引数valueに対応するTRUE/FALSEの文字列を返します。
		/// </summary>
		/// <param name="value">判定対象の値</param>
		/// <returns>TRUEまたはFALSE</returns>
		private String ConvertToBoolean(String value)
		{
			String result = ("0".Equals(value)) ? "FALSE" : "TRUE";
			return result;
		}
		
		/// <summary>
		/// 真偽型セルかを判定します。
		/// </summary>
		/// <returns>真偽型の場合はtrue</returns>
		private bool IsBoolean()
		{
			bool result = false;
			if (!IsEmpty() && null != this.cell.DataType)
			{
				if (CellValues.Boolean == this.cell.DataType.Value)
				{
					result = true;
				}
			}
			return result;
		}

		/// <summary>
		/// SharedStringTable参照セルかを判定します。
		/// </summary>
		/// <returns>SharedStringTable参照セルの場合はtrue</returns>
		private bool IsSharedStringTable()
		{
			bool result = false;
			if (!IsEmpty() && null != this.cell.DataType)
			{
				if (CellValues.SharedString == this.cell.DataType.Value)
				{
					result = true;
				}
			}
			return result;
		}

	}
}
